package com.zjq.shiro;

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.ArrayList;
import java.util.List;

/**
 * @author zjq
 * @date 2020/3/23 20:08
 * <p>title:自定义Realm</p>
 * <p>company:zjhcsoft</p>
 * <p>description:
 * Realm域：Shiro从Realm获取安全数据（如用户、角色、权限），就是说SecurityManager要验证用户身份，
 * 那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法；也需要从Realm得到用户相应的
 * 角色/权限进行验证用户是否能进行操作；可以把Realm看成DataSource，即安全数据源</p>
 */

/**
 * 自定义realm，需要继承AuthorizingRealm父类
 *     重写父类中的两个方法
 *         doGetAuthorizationInfo     ：授权
 *         doGetAuthenticationInfo     ：认证
 */
public class PermissionRealm extends AuthorizingRealm{

    @Override
    public String getName() {
        return "permissionRealm";
    }

    /**
     * 授权：
     *    授权的主要目的就是查询数据库获取用户的所有角色和权限信息
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 从principalCollection获取已认证的用户信息
        String username = (String) principalCollection.getPrimaryPrincipal();
        /**
        * 正式系统：应该从数据库中根据用户名或者id查询
        *         这里为了方便演示，手动构造
        */
        // 2.模拟从数据库中查询的用户所有权限
        List<String> permissions = new ArrayList<String>();
        permissions.add("user:save");// 用户的创建
        permissions.add("user:update");// 商品添加权限
        // 3.模拟从数据库中查询的用户所有角色
        List<String> roles = new ArrayList<String>();
        roles.add("role1");
        roles.add("role2");
        //4.构造用户权限数据
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addStringPermissions(permissions);
        simpleAuthorizationInfo.addRoles(roles);
        return simpleAuthorizationInfo;
    }

    /**
     * 认证：
     *     认证的主要目的，比较用户输入的用户名密码是否和数据库中的一致
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1.获取用户登陆的usernamePasswordToken
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
        //2.获取用户名和密码
        String username = usernamePasswordToken.getUsername();
        String password = String.valueOf(usernamePasswordToken.getPassword());

        /**
         * 正式应该从数据库查询校验用户名和密码
         *     测试为了方便直接比较密码为"123456"
         */
        if(!"123456".equals(password)){
            throw new RuntimeException();
        }else {
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,password,
            this.getName());
            return simpleAuthenticationInfo;
        }
    }
}
